﻿using System;
using System.IO;
using System.Text;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.ArgumentParser;

namespace WikiDoc
{
    /// <summary>
    /// WikiDoc 工具将输入的 XmlDoc 文档中的 Wiki 语法，转换为 Html 语法，
    /// 这样输出的 XmlDoc 文件就能够被 NDoc 等工具继续处理，转换为格式良好的帮助文件。
    /// 
    /// === 使用方法 ===
    /// WikiDoc.exe [XmlDoc文件名]
    /// 
    /// </summary>
    class Program
    {
        /// <summary>
        /// Mains the specified args.
        /// </summary>
        /// <param name="args">The args.</param>
        /// <returns></returns>
        /// <value></value>
        /// <remarks>
        /// 
        /// </remarks>
        static int Main(string[] args)
        {
            if (args == null || args.Length < 1)
            {
                Console.Error.WriteLine("缺少必需的参数");
                PrintUsage(Console.Error);
                return 1;
            }

            if (args[0] == "/?" || args[0] == "-?" || args[0] == "--help")
            {
                PrintUsage(Console.Out);
                return 0;
            }

            ArgumentDescCollection arguments = new ArgumentDescCollection();

            arguments.Add("source", ArgumentFlags.IsUnnamed | ArgumentFlags.Required);
            arguments.Add("encode", ArgumentFlags.IsSwitch, 'e');
            arguments.Add("out", ArgumentFlags.None, 'o');
            arguments.Add("for-summary", ArgumentFlags.IsSwitch, 'm');
            arguments.Add("replace", ArgumentFlags.IsSwitch, 'r');

            try
            {
                ArgumentParser.GetArguments(args, arguments);
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine(ex.Message);
                return 1;
            }

            string source = arguments["source"].Value;
            string outfile = arguments["out"].Value;

            Encoding encode = Encoding.UTF8;

            if (arguments["encode"].Value != null)
            {
                Console.Error.WriteLine("WARN: 现在还不支持 encode 参数。");
            }

            string tempfile = null;

            TextReader reader = null;
            TextWriter writer = null;
            
            try
            {

                if (arguments["replace"].Value != null)
                {
                    tempfile = Path.GetTempFileName();

                    File.Copy(source, tempfile, true);
                    
                    StreamReader rd = new StreamReader(tempfile, true);
                    reader = new StreamReader(tempfile, true);
                    writer = new StreamWriter(source, false, encode);
                }
                else
                {
                    reader = new StreamReader(source, true);

                    if (outfile == null)
                    {
                        writer = Console.Out;
                    }
                    else
                    {
                        writer = new StreamWriter(outfile, false, encode);
                    }
                }

                string line;

                IFormatter formatter;

                if (arguments["for-summary"].Value == null)
                {
                    formatter = new Formatter.XmlDocFormatter(writer);
                }
                else
                {
                    formatter = new Formatter.XmlDocSummaryFormatter(writer);
                }

                WikiTranslater translater = new WikiTranslater();

                Collection<XmlDocPicker> pickers = new Collection<XmlDocPicker>();

                pickers.Add(new XmlDocPicker("summary", reader));
                pickers.Add(new XmlDocPicker("remarks", reader));
                pickers.Add(new XmlDocPicker("value", reader));
                pickers.Add(new XmlDocPicker("returns", reader));

                while ((line = reader.ReadLine()) != null)
                {
                    bool picked = false;

                    foreach (XmlDocPicker picker in pickers)
                    {
                        if (line.EndsWith(picker.StartSign, StringComparison.Ordinal))
                        {
                            writer.WriteLine(line);

                            picker.Reset();
                            picker.IndentLevel = line.Length - line.TrimStart().Length;

                            translater.Parse(picker.Reader, formatter);

                            writer.Write(new string(' ', picker.IndentLevel));
                            writer.WriteLine(picker.EndSign);

                            picked = true;
                            break;
                        }
                    }

                    if (!picked)
                    {
                        writer.WriteLine(line);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine(ex.Message);
                Console.Error.WriteLine(ex.StackTrace);
                return 1;
            }
            finally
            {
                if (reader != null)
                {
                    try
                    {
                        reader.Close();
                    }
                    catch
                    {
                    }
                }

                if (writer != null)
                {
                    try
                    {
                        writer.Close();
                    }
                    catch
                    {
                    }
                }

                if (tempfile != null)
                {
                    try
                    {
                        File.Delete(tempfile);
                    }
                    catch
                    {                        
                    }
                }
            }

            return 0;
        }

        private static void PrintUsage(TextWriter writer)
        {
            System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
            string assembleName = assembly.GetName().Name;
            System.IO.Stream stream = assembly.GetManifestResourceStream(assembleName + ".Usage.txt");
            foreach (string name in assembly.GetManifestResourceNames())
	        {
                System.Diagnostics.Debug.WriteLine(name);
	        }

            using (stream)
            using (System.IO.TextReader reader = new System.IO.StreamReader(stream, true))
            {
                writer.WriteLine(reader.ReadToEnd());
            }
        }
    }
}
